﻿using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Halk.Builder;
using Halk.Config;
using Halk.Dao;
using Halk.Model;
using Halk.Utils;

namespace Halk.Spider
{
    public class SpiderMover
    {
        #region 变量定义

        private readonly Dictionary<string, DaoArticle> _mapsArticleDao = new Dictionary<string, DaoArticle>();

        private readonly Dictionary<string, DaoChapter> _mapsChapterDao = new Dictionary<string, DaoChapter>();

        private readonly Dictionary<string, DaoAttachs> _mapsAttachDao = new Dictionary<string, DaoAttachs>();

        private readonly Dictionary<string, int> _mapsArticleId = new Dictionary<string, int>();

        private readonly Dictionary<string, int> _mapsChapterId = new Dictionary<string, int>();

        private readonly Dictionary<string, int> _mapsAttachId = new Dictionary<string, int>();

        private readonly Dictionary<string, HtmlBuilder> _mapsHtmlBuilder = new Dictionary<string, HtmlBuilder>();

        private string _flagTarget;

        private string _flagSource;

        private int _repeatTimes;

        private int _articleIndex;

        private ArticleInfo _articleTarget = new ArticleInfo();

        private readonly OpfBuilder _opfBuilder = new OpfBuilder();

        private IList<ArticleInfo> _articleListSource = new List<ArticleInfo>();

        private IList<ChapterInfo> _chapterListTarget = new List<ChapterInfo>();

        private IList<ChapterInfo> _chapterListSource = new List<ChapterInfo>();

        private ArticleInfo _lastInfo = new ArticleInfo();

        #endregion

        private void Initialize()
        {
            ConfigManage.Instace().Load();
            ContentManage.Instace().Load();
            for (var i = 0; i < ConfigManage.Instace().GetSize(); ++i)
            {
                if (!ConfigManage.Instace().GetConfig().IsActive.Equals(1))
                {
                    ConfigManage.Instace().MoveNext();
                    continue;
                }
                var targtet = ConfigManage.Instace().GetConfig().flag + "target";
                var source = ConfigManage.Instace().GetConfig().flag + "source";

                #region target

                if (!_mapsArticleDao.ContainsKey(targtet))
                {
                    var targetDaoArticle = new DaoArticle(ConfigManage.Instace().GetConfig().TargetConnString);
                    _mapsArticleDao[targtet] = targetDaoArticle;
                    _mapsArticleId[targtet] = targetDaoArticle.GetArticleMaxId();
                }
                if (!_mapsChapterDao.ContainsKey(targtet))
                {
                    var dao = new DaoChapter(ConfigManage.Instace().GetConfig().TargetConnString);
                    _mapsChapterDao[targtet] = dao;
                    _mapsChapterId[targtet] = dao.GetChapterMaxId();
                }
                if (!_mapsAttachDao.ContainsKey(targtet))
                {
                    var dao = new DaoAttachs(ConfigManage.Instace().GetConfig().TargetConnString);
                    _mapsAttachDao[targtet] = dao;
                    _mapsAttachId[targtet] = dao.GetAttachMaxID();
                }

                #endregion

                #region source

                if (!_mapsArticleDao.ContainsKey(source))
                {
                    var sourceDaoArticle = new DaoArticle(ConfigManage.Instace().GetConfig().ConnString);
                    _mapsArticleDao[source] = sourceDaoArticle;
                }
                if (!_mapsChapterDao.ContainsKey(source))
                {
                    var dao = new DaoChapter(ConfigManage.Instace().GetConfig().ConnString);
                    _mapsChapterDao[source] = dao;
                }
                if (!_mapsAttachDao.ContainsKey(source))
                {
                    var dao = new DaoAttachs(ConfigManage.Instace().GetConfig().ConnString);
                    _mapsAttachDao[source] = dao;
                }
                if (!_mapsHtmlBuilder.ContainsKey(targtet))
                {
                    var htmlBuilder = new HtmlBuilder(ConfigManage.Instace().GetConfig());
                    htmlBuilder.LoadDefineFile();
                    htmlBuilder.LoadTheme();
                    _mapsHtmlBuilder[targtet] = htmlBuilder;
                }

                #endregion

                ConfigManage.Instace().MoveNext();
            }
        }

        public void Work()
        {
            Initialize();
            ConfigManage.Instace().MoveFirst();
            for (var i = 0; i < ConfigManage.Instace().GetSize(); i++)
            {
                if (ConfigManage.Instace().GetConfig().IsActive.Equals(1))
                {
                    _flagSource = ConfigManage.Instace().GetConfig().flag + "source";
                    _flagTarget = ConfigManage.Instace().GetConfig().flag + "target";
                    GetNovelList();
                }
                ConfigManage.Instace().MoveNext();
            }
        }

        private void GetNovelList()
        {
            //获取更新时间大于记录时间的列表
            _articleListSource =
                _mapsArticleDao[_flagSource].GetListByUpdateTime(ConfigManage.Instace().GetConfig().RuleFlag,
                                                                 ConfigManage.Instace().GetConfig().LastUpdate);
            if (_articleListSource.Count == 0)
            {
                System.Threading.Thread.Sleep(ConfigManage.Instace().GetConfig().SleepTimes);
                return;
            }
            //重复次数置零
            _repeatTimes = 0;
            for (_articleIndex = 2;
                 //从第3本开始更新
                 _articleIndex < _articleListSource.Count &&
                 _repeatTimes < ConfigManage.Instace().GetConfig().RepeatMax &&
                 SystemManage.Instace().GetOnOff();
                 _articleIndex++)
            {
                if (!GetNovel())
                    continue;

                GetChapters();
                if (_lastInfo.lastchapterid > 0 && !string.IsNullOrEmpty(_lastInfo.lastchapter))
                    _mapsArticleDao[_flagTarget].Update(_lastInfo);
                //CompleteNovel();?san
                //更新lastchapterid lastchapter
              
            }

            //获取上次未匹配到最新章节的列表
            _articleListSource.Clear();
            _articleListSource = _mapsArticleDao[_flagSource].GetListNotMatchBest();
            for (_articleIndex = 0;
                 _articleIndex < _articleListSource.Count &&
                 _repeatTimes < ConfigManage.Instace().GetConfig().RepeatMax &&
                 SystemManage.Instace().GetOnOff();
                 _articleIndex++)
            {
                if (!GetNovel())
                    continue;

                GetChapters();
                CompleteNovel();
            }
            ConfigManage.Instace().Save();
        }

        /// <summary>
        /// 获取该书article内容
        /// </summary>
        /// <returns></returns>
        private bool GetNovel()
        {
            _articleTarget = _mapsArticleDao[_flagTarget].GetByName(_articleListSource[_articleIndex].articlename);
            var exists = _articleTarget.articleid != 0;
            if (!exists)
            {
                _articleTarget = _articleListSource[_articleIndex];
                _articleTarget.lastchapter = "";
                _articleTarget.lastchapterid = 0;
                _articleTarget.lastvolume = "";
                _articleTarget.lastvolumeid = 0;
                _articleTarget.articleid = _mapsArticleId[_flagTarget];
                _articleTarget.postdate = TimeHelper.GetDateInt();
                _articleTarget.lastupdate = TimeHelper.GetDateInt();
                _mapsArticleDao[_flagTarget].Add(_articleTarget);
                _lastInfo = _articleTarget; //最新章节及ID未更新
                _mapsArticleId[_flagTarget]++;
            }
            _opfBuilder.AddMetadata(_articleTarget);
            _chapterListSource = _mapsChapterDao[_flagSource].GetList(_articleListSource[_articleIndex].articleid,
                                                                      ConfigManage.Instace().GetConfig().RuleFlag);
            if (exists)
            {
                _chapterListTarget = _mapsChapterDao[_flagTarget].GetList(_articleTarget.articleid);
                if (_chapterListSource.Count == _chapterListTarget.Count
                    && !_articleTarget.firstflag.Equals(1))//未匹配到最优的书籍
                {
                    _repeatTimes++;
                    ConfigManage.Instace().GetConfig().LastUpdate =
                        _articleListSource[_articleIndex].lastupdate.ToString(CultureInfo.InvariantCulture);
                    return false;
                }
            }
            else
            {
                _articleTarget.downloadlink = string.Format("{0}/files/article/txtfull/{1}/{2}.txt",
                                                            ConfigManage.Instace().GetConfig().TargetDomain,
                                                            _articleListSource[_articleIndex].articleid/1000,
                                                            _articleListSource[_articleIndex].articleid);
            }
            //if (!string.IsNullOrEmpty(_articleTarget.coverlink))
            //{
            //    NovelStore.Instace().StoreCover(_articleTarget, Encoding.UTF8,
            //                                    ConfigManage.Instace().GetConfig().FilePath);
            //}
            return true;
        }

        /// <summary>
        /// 获取该书的章节
        /// </summary>
        private void GetChapters()
        {
            int hasVipChapter = 0;
            for (var ci = 0; ci < _chapterListSource.Count; ci++)
            {
                if (_chapterListTarget.Count > ci) //目标站原来章节已存在
                {
                    _opfBuilder.AddMainfestAndSpine(_chapterListTarget[ci]);
                }
                else
                {
                    //var chapter = _chapterListSource[ci];
                    _chapterListTarget.Add(_chapterListSource[ci]);
                    _chapterListTarget[ci].articleid = _articleTarget.articleid;
                    _chapterListTarget[ci].chapterid = _mapsChapterId[_flagTarget];
                    _chapterListTarget[ci].isnew = 1;
                    if (_chapterListTarget[ci].isvip.Equals(1))
                    {
                        hasVipChapter++;
                    }
                    //else if (!_chapterListTarget[ci].chaptertype.Equals(1)) //章节
                    //{
                    //    NovelStore.Instace().GetChapter(_chapterListTarget[ci]); //非会员小说开始采集
                    //}

                    if (_chapterListTarget[ci].chaptertype != 1 && _chapterListTarget[ci].isnew != 0)
                    {
                        #region set last info

                        _lastInfo.articleid = _chapterListTarget[ci].articleid;
                        _lastInfo.lastchapterid = _chapterListTarget[ci].chapterid;
                        _lastInfo.lastchapter = _chapterListTarget[ci].chaptername;
                        _lastInfo.lastvolumeid = _chapterListTarget[ci].volumeid;
                        _lastInfo.chapters++;

                        #endregion
                    }

                    _mapsChapterDao[_flagTarget].Add(_chapterListTarget[ci]);
                    _mapsChapterId[_flagTarget]++;
                }
            }
            //有新增加的VIP章节或书籍未匹配到最佳
            if (hasVipChapter > 0 || _articleListSource[_articleIndex].firstflag.Equals(1))
            {
                GetVipChapters();
            }
        }

        /// <summary>
        /// 生成该书对应的HTML文件
        /// </summary>
        private void CompleteNovel()
        {
            if (!_opfBuilder.ConfirmOptFile(ConfigManage.Instace().GetConfig().FilePath, _articleTarget.articleid))
                return;

            _mapsHtmlBuilder[_flagTarget].CreateIndexHtml(_articleTarget, _chapterListTarget);
            ConfigManage.Instace().GetConfig().LastUpdate = _articleListSource[_articleIndex].lastupdate.ToString(CultureInfo.InvariantCulture);
        }

        /// <summary>
        /// 存储所有备用规则与QIDIAN之间匹配的章节映射
        /// </summary>
        private readonly Dictionary<string, Dictionary<int, int>> _reserveRelations = new Dictionary<string, Dictionary<int, int>>();
       
        /// <summary>
        /// 差别信息
        /// </summary>
        private class DiffernceInfo
        {
            public string Webflag { get; set; }
            public int Difference { get; set; }
        }

        /// <summary>
        /// 存储差别信息
        /// </summary>
        private readonly IList<DiffernceInfo> _reserveDifferences = new List<DiffernceInfo>();

        /// <summary>
        /// 存储该书在所有备用站点的目录
        /// </summary>
        private readonly Dictionary<string, IList<ChapterInfo>> _reserveBookReader =
            new Dictionary<string, IList<ChapterInfo>>();

        /// <summary>
        /// 获取VIP章节信息
        /// </summary>
        private void GetVipChapters()
        {
            bool hasBestBefore;
            var reserveFlags = SmartMatch.Instace().GetReserveFlag(_articleTarget.articleid, out hasBestBefore);
            _reserveRelations.Clear();
            _reserveDifferences.Clear();
            var article = _articleListSource[_articleIndex];//源
            foreach (var reserveflag in reserveFlags)
            {
                //按照articleid与webflag获取匹配源的目录
                var reserveChapters = _mapsChapterDao[_flagSource].GetList(article.articleid, reserveflag);
                _reserveBookReader[reserveflag] = reserveChapters;
                if (reserveChapters.Count == 0)continue;
                
                int difference = 0;
                var relations = new Dictionary<int, int>();
                var hasBest = SmartMatch.Instace().MatchChapters(_chapterListTarget, reserveChapters, ref difference, ref relations);
                if (hasBest)
                {
                    Utils.LogManage.Instace().Info(true,
                                                   string.Format("[BEST]{0}{1}", article.articlename,
                                                                 article.contentslink));

                    //NovelStore.Instace().DownloadTxtReserve(_chapterListTarget, reserveChapters, relations, reserveflag);
                    NovelStore.Instace().SaveBestMatch(article, reserveflag, hasBestBefore);

                    //更新匹配最优标记
                    _mapsArticleDao[_flagSource].UpdateNotBest(_articleListSource[_articleIndex].articleid,0);
                }
                else
                {
                    _reserveRelations[reserveflag] = relations; //将章节映射关系存入
                    _reserveDifferences.Add(new DiffernceInfo { Webflag = reserveflag, Difference = difference });
                }
            }
            //所有备用站点未查询出best，则取用difference最少的规则
            if (_reserveDifferences.Count > 0)
            {
                var items = from s in _reserveDifferences
                            orderby s.Difference descending
                            select s;
                var diff = items.First();
                //NovelStore.Instace().DownloadTxtReserve(_chapterListTarget,
                //                                        _reserveBookReader[diff.Webflag],
                //                                        _reserveRelations[diff.Webflag], 
                //                                        diff.Webflag);
                //更新未匹配最优标记
                _mapsArticleDao[_flagSource].UpdateNotBest(_articleListSource[_articleIndex].articleid,1);
            }
        }
    }
}
